package com.youtills.resource;

import com.youtills.core.lang.InstanceMaker;
import com.youtills.action.ActionContext;

import java.util.List;

/**
 * TODO - !!!doc me!!!
 *
 * @author ravi.chiluveru
 * @since 23.0 (10/4/14)
 */
public interface ResourceManager {

    ResourceManager instance = new Singleton();

    <T extends Resource> T newResource(ActionContext ac, Class<T> clazz);
    <T extends Resource> T getResource(ActionContext ac, Class<T> clazz, long resourceId);

    <T extends Resource> List<T> getResourcesBulk(ActionContext ac, Class<T> clazz, Long... resourceIds);

    <T extends Resource> List<T> getResources(ActionContext ac, Class<T> clazz, ResourceFilter filter);

    <T extends ChildResource> T newChildResource(ActionContext ac, Class<T> clazz, long parentResourceType, long parentResourceId);
    <T extends ChildResource> List<T> getChildResources(ActionContext ac, Class<T> clazz, long parentResourceType, long parentResourceId);

    <T extends Resource> boolean saveResource(ActionContext ac, T resource);

    <T extends Resource> List<T> getLinkedResources(ActionContext ac, Resource resource, ResourceLink link);

    class Singleton implements ResourceManager {

        private final ResourceManager defaultManager;
        private final InstanceMaker<ResourceManager> instanceMaker = new InstanceMaker<>(true);

        private Singleton() {
            defaultManager = MySqlResourceStorage.getInstance();
        }

        public final <T extends Resource> T getResource(ActionContext ac, Class<T> clazz, long resourceId) {
            return manager(clazz).getResource(ac, clazz, resourceId);
        }

        public final <T extends Resource> T newResource(ActionContext ac, Class<T> clazz) {
            return manager(clazz).newResource(ac, clazz);
        }

        public final <T extends ChildResource> List<T> getChildResources(ActionContext ac, Class<T> clazz, long parentResourceType, long parentResourceId) {
            return manager(clazz).getChildResources(ac, clazz, parentResourceType, parentResourceId);
        }

        public final <T extends ChildResource> T newChildResource(ActionContext ac, Class<T> clazz, long parentResourceType, long parentResourceId) {
            return manager(clazz).newChildResource(ac, clazz, parentResourceType, parentResourceId);
        }

        public final <T extends Resource> boolean saveResource(ActionContext ac, T resource) {
            return manager(resource.getClass()).saveResource(ac, resource);
        }

        @Override
        public <T extends Resource> List<T> getResources(ActionContext ac, Class<T> clazz, ResourceFilter filter) {
            return manager(clazz).getResources(ac, clazz, filter);
        }

        @Override
        public <T extends Resource> List<T> getLinkedResources(ActionContext ac, Resource resource, ResourceLink link) {
            return manager(resource.getClass()).getLinkedResources(ac, resource, link);
        }

        @Override
        public <T extends Resource> List<T> getResourcesBulk(ActionContext ac, Class<T> clazz, Long... resourceIds) {
            return manager(clazz).getResourcesBulk(ac, clazz, resourceIds);
        }

        private <T extends Resource> ResourceManager manager(Class<T> clazz){
            //TODO - get manager with annotation.
            return defaultManager;
        }
    }

}
